package com.ncf.rpc.server;

import java.lang.reflect.Method;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ncf.rpc.common.NCFRequest;
import com.ncf.rpc.common.NCFResponse;

import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class NCFHandler extends SimpleChannelInboundHandler<NCFRequest> {

	private static final Logger logger = LoggerFactory.getLogger(NCFHandler.class);

	private final Map<String, Object> handlerMap;

	public NCFHandler(Map<String, Object> handlerMap) {
		this.handlerMap = handlerMap;
	}

	/**
	 * 接收消息，处理消息，返回结果
	 */
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, NCFRequest request)
			throws Exception {
		NCFResponse response = new NCFResponse();
		response.setRequestId(request.getRequestId());
		try {
			// 根据request来处理具体的业务调用
			Object result = handle(request);
			response.setResult(result);
		} catch (Throwable t) {
			response.setError(t);
		}
		// 写入 outbundle（即RpcEncoder）进行下一步处理（即编码）后发送到channel中给客户端
		ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
	}

	/**
	 * 根据request来处理具体的业务调用 调用是通过反射的方式来完成
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 * @throws Throwable
	 */
	private Object handle(NCFRequest request) throws Exception {
		String className = request.getClassName();

		// 拿到实现类对象
		Object serviceBean = handlerMap.get(className);

		// 拿到要调用的方法名、参数类型、参数值
		String methodName = request.getMethodName();
		Class<?>[] parameterTypes = request.getParameterTypes();// 参数类型
		Object[] parameters = request.getParameters();// 参数

		// 拿到接口类
		Class<?> forName = Class.forName(className);

		Method method = forName.getMethod(methodName, parameterTypes);
		return method.invoke(serviceBean, parameters);
	}

}
